package com.tingyuge.base.thread.lock;

import lombok.Data;

import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.IntStream;

/**
 * @author xiaodao
 * @version 1.0
 * @date 2021/3/6
 * Thread.sleep与await （或者是object 的wait方法）本质区别：sleep方法不会释放锁，而await方法会释放锁，并且在signal后，还需要从新获取到锁之后才会执行
 */
public class LockTest2 {
    public static void main(String[] args) throws InterruptedException {
        BoundedContainer boundedContainer = new BoundedContainer();
        IntStream.range(0,10).forEach(i->{

            new Thread(()->{
                boundedContainer.take();
            }).start();
        });
        IntStream.range(0,10).forEach(i->{
            new Thread(()->{
                boundedContainer.put("hello");
            }).start();
        });

    }

}


class BoundedContainer{
   private String[] elements = new String[10];
   /**
    * 数组中已有的元素的数量
    */
   private int elementCount;
   private Lock lock = new ReentrantLock();
   private Condition notEmpty = lock.newCondition();
   private Condition notFull  = lock.newCondition();
   /**
    * 从哪个位置放元素
    */
   private int putIndex;
   /**
    * 从哪个位置取元素
    */
   private int takeIndex;


   public void put(String str){
       lock.lock();
       try {
           while (elementCount == elements.length){
               System.out.println("释放");
               notFull.await();
           }

           elements[putIndex++] = str;
           putIndex =putIndex%elements.length;
           ++elementCount;
           System.out.println("into element" + Arrays.toString(elements));
           notEmpty.signal();
       }catch (Exception e){

       }finally {
           lock.unlock();
       }

   }
   public String take(){
       lock.lock();
       try {
           while (elementCount ==0){
               notEmpty.await();
           }
           String str =elements[takeIndex];
           elements[takeIndex++] = null;
           --elementCount;
           System.out.println("get element "+  Arrays.toString(elements));
           takeIndex = takeIndex%elements.length;
           notFull.signal();
           return str ;
       }catch (Exception e){

       }finally {
           lock.unlock();
       }
       return null;
   }
}
